package com.mezz.bones.im.logic.service.impl;

import com.alibaba.fastjson.JSONObject;
import com.esotericsoftware.minlog.Log;
import com.mezz.bones.im.common.enums.RelationTypeEnum;
import com.mezz.bones.im.common.enums.SessionTypeEnum;
import com.mezz.bones.im.common.exception.ImBaseException;
import com.mezz.bones.im.common.message.base.MessageHeader;
import com.mezz.bones.im.common.message.body.in.PrivateMessageCreateReq;
import com.mezz.bones.im.common.message.body.in.PrivateMessageRecordReq;
import com.mezz.bones.im.common.message.body.in.PrivateMessageRemoveReq;
import com.mezz.bones.im.common.message.body.out.PrivateMessageRecordRes;
import com.mezz.bones.im.common.domain.user.ImUserBaseInfo;
import com.mezz.bones.im.common.domain.user.ImUserConnectInfo;
import com.mezz.bones.im.common.result.ImResultCode;
import com.mezz.bones.im.common.util.MessageUtil;
import com.mezz.bones.im.common.util.SessionIdUtil;
import com.mezz.bones.im.logic.domain.bo.ChatConversationInitBo;
import com.mezz.bones.im.logic.domain.context.PrivateMessageCreateCtx;
import com.mezz.bones.im.logic.domain.entity.ChatConversation;
import com.mezz.bones.im.logic.domain.entity.ChatPrivateMessageRecord;
import com.mezz.bones.im.logic.domain.entity.ChatPrivateMessageInfo;
import com.mezz.bones.im.logic.domain.entity.ChatUser;
import com.mezz.bones.im.logic.domain.request.ApiPrivateMessageCreateRequest;
import com.mezz.bones.im.logic.repository.IChatConversationRepository;
import com.mezz.bones.im.logic.repository.IChatPrivateMessageInfoRepository;
import com.mezz.bones.im.logic.repository.IChatPrivateMessageRecordRepository;
import com.mezz.bones.im.logic.repository.IChatUserRemarkRepository;
import com.mezz.bones.im.logic.service.IChatConversationService;
import com.mezz.bones.im.logic.service.IChatPrivateMessageService;
import com.mezz.bones.im.logic.service.IChatUserService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Author: zhuang
 * @Date: 2024/12/20 17:47
 * @Description: TODO
 * @Version: 1.0
 **/

@Service
@Slf4j
public class ChatPrivateMessageServiceImpl implements IChatPrivateMessageService {

    @Resource
    private IChatPrivateMessageRecordRepository privateMessageRecordRepository;

    @Resource
    private IChatPrivateMessageInfoRepository privateMessageInfoRepository;

    @Resource
    private IChatUserService chatUserService;

    @Resource
    private IChatUserRemarkRepository chatUserRemarkRepository;

    @Resource
    private IChatConversationRepository chatConversationRepository;

    @Override
    public void saveMessagePrivate(PrivateMessageCreateCtx context) {

        ChatUser sender = context.getSender();
        ChatUser receiver = context.getReceiver();
        ChatUser relationInfo = context.getRelationInfo();

        ImUserConnectInfo senderUserConnectInfo = context.getSenderUserConnectInfo();
        //发送者设备IP地址
        String senderIp = senderUserConnectInfo.getIp();
        String deviceType = senderUserConnectInfo.getDeviceType();
        String imei = senderUserConnectInfo.getImei();

        MessageHeader header = context.getHeader();
        PrivateMessageCreateReq body = context.getBody();
        String userId = body.getUserId();
        String userType = sender.getUserType();

        String peerId = body.getPeerId();
        String peerType = receiver.getUserType();

        String relationId = body.getRelationId();

        String msgKey = body.getMsgKey();
        String msgSeq = body.getMsgSeq();
        Integer msgType = body.getMsgType();
        JSONObject content = body.getContent();
        String contentType = body.getContentType();
        JSONObject msgExtra = body.getMsgExtra();
        Date now = context.getNow();

        Integer sync2Peer = body.getSync2Peer();

        //消息记录表落库 发送放角度
        ChatPrivateMessageRecord sendMessage = new ChatPrivateMessageRecord();
        sendMessage.setMsgKey(msgKey);
        sendMessage.setUserId(userId);
        sendMessage.setUserType(userType);
        sendMessage.setPeerId(peerId);
        sendMessage.setPeerType(peerType);

        sendMessage.setRelationId(body.getRelationId());
        sendMessage.setRelationType(MessageUtil.relationType(userType,peerType,relationId));

        //保存客服相关 上下文信息
        context.setSenderRelationTypeEnum(RelationTypeEnum.findEnum(sendMessage.getRelationType()));

        sendMessage.setSessionId(SessionIdUtil.buildSessionId(userId,peerId));
        sendMessage.setDirection(0);
        sendMessage.setMsgSeq(msgSeq);
        sendMessage.setMsgType(msgType);
        sendMessage.setContentType(contentType);
        sendMessage.setUserRecalled(0);
        sendMessage.setUserDel(0);
        sendMessage.setCreateTime(now);
        sendMessage.setUpdateTime(now);
        sendMessage.setIsDel(0);
        privateMessageRecordRepository.save(sendMessage);
        context.setUserMsgRecordId(sendMessage.getId());
        context.setUserConversationInitBo(buildChatConversationInitBo(sendMessage));


        //接收方角度
        ChatPrivateMessageRecord receiveMessage = new ChatPrivateMessageRecord();
        receiveMessage.setMsgKey(msgKey);
        receiveMessage.setUserId(peerId);
        receiveMessage.setUserType(receiver.getUserType());
        receiveMessage.setPeerId(userId);
        receiveMessage.setPeerType(sender.getUserType());
        receiveMessage.setDirection(1);
        receiveMessage.setMsgSeq(msgSeq);
        receiveMessage.setMsgType(msgType);
        receiveMessage.setContentType(contentType);
        receiveMessage.setUserRecalled(0);
        receiveMessage.setUserDel(0);
        receiveMessage.setCreateTime(now);
        receiveMessage.setUpdateTime(now);
        receiveMessage.setIsDel(0);

        //如果是客服业务相关的数据
        if(!sendMessage.getRelationType().equals(RelationTypeEnum.NONE.getCode())){

            if(RelationTypeEnum.SUB.getCode().equals(sendMessage.getRelationType())){
                //如果发送端是 被服务方 存的是客服ID信息
                //被服务方 供应商/平台 供应商/平台客服ID
                //供应商/平台客服ID 被服务方 供应商/平台
                receiveMessage.setUserId(relationInfo.getUserId());
                receiveMessage.setUserType(relationInfo.getUserType());

                receiveMessage.setPeerId(userId);
                receiveMessage.setPeerType(userType);

                receiveMessage.setRelationId(peerId);
                receiveMessage.setRelationType(MessageUtil.relationType(receiveMessage.getUserType(),receiveMessage.getPeerType(),receiveMessage.getRelationId()));
            }

            if(RelationTypeEnum.MAIN.getCode().equals(sendMessage.getRelationType())){
                //如果发送端是 客服方 存的是客服对应的主体ID 供应商ID/平台ID
                //供应商/平台客服ID 被服务方 供应商/平台
                //被服务方 供应商/平台 供应商/平台客服ID

                receiveMessage.setUserId(peerId);
                receiveMessage.setUserType(peerType);

                receiveMessage.setPeerId(relationInfo.getUserId());
                receiveMessage.setPeerType(relationInfo.getUserType());

                receiveMessage.setRelationId(userId);
                receiveMessage.setRelationType(MessageUtil.relationType(receiveMessage.getUserType(),receiveMessage.getPeerType(),receiveMessage.getRelationId()));
            }

        }

        receiveMessage.setSessionId(SessionIdUtil.buildSessionId(receiveMessage.getUserId(),receiveMessage.getPeerId()));

        if(sync2Peer == 1){
            privateMessageRecordRepository.save(receiveMessage);
        }

        context.setPeerConversationInitBo(buildChatConversationInitBo(receiveMessage));
        context.setPeerMsgRecordId(receiveMessage.getId());

        //消息基础扩展信息落库
        ChatPrivateMessageInfo ext = new ChatPrivateMessageInfo();
        ext.setMsgKey(msgKey);
        ext.setContent(content);
        ext.setMsgExtra(msgExtra);
        ext.setUserId(userId);
        ext.setPeerId(peerId);
        ext.setUserIp(senderIp);
        ext.setUserDeviceType(deviceType);
        ext.setUserImei(imei);
        ext.setCreateTime(now);
        ext.setUpdateTime(now);
        ext.setIsDel(0);
        privateMessageInfoRepository.save(ext);
    }

    private ChatConversationInitBo buildChatConversationInitBo(ChatPrivateMessageRecord record) {

        return ChatConversationInitBo.builder()
                .now(record.getCreateTime())
                .userId(record.getUserId())
                .userType(record.getUserType())
                .peerId(record.getPeerId())
                .peerType(record.getPeerType())
                .relationId(record.getRelationId())
                .relationType(record.getRelationType())
                .sessionTypeEnum(SessionTypeEnum.PRIVATE)
                .build();

    }

    @Override
    public boolean existsMsgKey(String msgKey) {
        return privateMessageRecordRepository.existsMsgKey(msgKey);
    }

    @Override
    public List<PrivateMessageRecordRes> getUserPrivateMessagePage(PrivateMessageRecordReq req) {

        //用户信息验证
        ImUserBaseInfo peerUserBaseInfo = chatUserService.getUserBaseInfo(req.getPeerId());
        if(peerUserBaseInfo == null){
            throw new ImBaseException(ImResultCode.DATA_NOT_FOUND,"对端用户不存在!");
        }

        ChatConversation conversation = chatConversationRepository.getByUserIdAndPeerId(req.getUserId(), req.getPeerId());

        //单聊消息记录基础新信息
        List<ChatPrivateMessageRecord> records = this.privateMessageRecordRepository.getUserPrivateMessagePage(req);

        if(records.isEmpty()){
            return new ArrayList<>();
        }

        //单聊的其他扩展消息数据
        List<String> msgKeys = records.stream().map(ChatPrivateMessageRecord::getMsgKey).distinct().collect(Collectors.toList());
        List<ChatPrivateMessageInfo> messageInfos = privateMessageInfoRepository.listByMsgKey(msgKeys);
        Map<String, ChatPrivateMessageInfo> messageInfoMap = messageInfos.stream().collect(Collectors.toMap(
                ChatPrivateMessageInfo::getMsgKey,
                item -> item
        ));

        //会话双方用户信息
        Set<String> userIds = new HashSet<>();
        for (ChatPrivateMessageRecord record : records) {
            userIds.add(record.getUserId());
            userIds.add(record.getPeerId());
            userIds.add(record.getRelationId());
        }

        //用户的信息
        Map<String, ChatUser> userMap = chatUserService.getByUserIds(userIds).stream().collect(Collectors.toMap(
                ChatUser::getUserId,
                item -> item
        ));

        //昵称备注的信息 只有单聊
        String peerRemarkNickname;
        if (conversation.getRelationType().equals(RelationTypeEnum.NONE.getCode())) {
            peerRemarkNickname = chatUserRemarkRepository.getPeerRemarkNickname(req.getUserId(), req.getPeerId());
        } else {
            peerRemarkNickname = "";
        }

        return records.stream().map(item ->{

            PrivateMessageRecordRes res = new PrivateMessageRecordRes();
            res.setId(item.getId());
            res.setMsgKey(item.getMsgKey());
            res.setUserId(item.getUserId());
            ChatUser userInfo = userMap.get(item.getUserId());
            res.setUserNickname(userInfo.getNickname());

            //对端用户
            ChatUser peerInfo = userMap.get(item.getPeerId());
            ChatUser relationInfo = userMap.get(item.getRelationId());

            if (conversation.getRelationType().equals(RelationTypeEnum.NONE.getCode())) {
                //如果是普通用户单聊
                res.setPeerNickname(peerInfo.getNickname());
                res.setPeerRemarkName(peerRemarkNickname);
            } else  {

                //客服消息 要展示具体的客服名称
                if( item.getRelationType().equals(RelationTypeEnum.SUB.getCode())) {
                    //用户 - 供应商的会话信息 要展示不同的客服信息
                    //客服信息是relationInfo
                    res.setPeerNickname(relationInfo.getNickname());
                    res.setPeerRemarkName("");
                }

                if(item.getRelationType().equals(RelationTypeEnum.MAIN.getCode())) {
                    // 供应商 - 用户会话信息
                    res.setPeerNickname(peerInfo.getNickname());
                    res.setPeerNickname("");
                }

            }

            res.setDirection(item.getDirection());
            res.setMsgSeq(item.getMsgSeq());
            res.setMsgType(item.getMsgType());
            res.setContentType(item.getContentType());
            res.setUserRecalled(item.getUserRecalled());
            res.setCreateTime(item.getCreateTime());

            ChatPrivateMessageInfo messageInfo = messageInfoMap.get(item.getMsgKey());
            //消息其他信息
            res.setContent(messageInfo.getContent());
            res.setMsgExtra(messageInfo.getMsgExtra());
            return res;
        }).collect(Collectors.toList());

    }

    @Override
    public void userPrivateMessageRemove(PrivateMessageRemoveReq req) {

        ChatPrivateMessageRecord messageInfo = privateMessageRecordRepository.getMsgByUserIdAndKey(req.getUserId(),req.getMsgKey());
        if(messageInfo == null){
            log.warn("用户消息不存在! userId:[{}],msgKey:[{}]",req.getUserId(),req.getMsgKey());
        }

        if (!messageInfo.getUserId().equals(req.getUserId())) {
            throw new ImBaseException(ImResultCode.ILLEGAL_OPERATION);
        }

        //消息记录删除
        //会话中 最后一条消息数据更新(可能删的是最后一条消息)
        privateMessageRecordRepository.userMsgRemove(messageInfo.getId());


    }

    @Override
    public void apiCreatePrivateMessage(ApiPrivateMessageCreateRequest request) {

    }
}
